现在的大趋势是全站https,所以我也折腾了一下https,用的是let’s Encrypt的证书,然后使用nginx做https服务器,顺便也升级了一下到http2.0。
let’s Encrypt
使用非常简单,按照教程做就可以了。我这里用的是自动配置的方式,也提供高级的自定义配置。
- 下载安装脚本并安装
1 | wget https://dl.eff.org/certbot-auto |
- 指定目录校验网站并生成证书
1 | ./certbot-auto certonly --webroot -w /var/www/example -d example.com -d www.example.com -w /var/www/thing -d thing.is -d m.thing.is |
生成证书后注意控制台的输出,到相应的live目录中获取生成的证书。
1 | README:说明文件 |
- 配置证书到nginx服务器配置中
1 | ssl on; |
定期更新
使用更新命令
1
/srv/certbot-auto renew
/etc/letsencrypt/live/qieguo.me目录下会生成所需的认证套件,将其复制到/alidata/server/nginx/conf/ssl/下即可
1
cp /etc/letsencrypt/live/qieguo.me/* /alidata/server/nginx/conf/ssl/
重启nginx
1
/alidata/server/nginx/sbin/nginx -s reload
将上述操作用crontab做成定时任务
1
2
3
4
5
6#!/bin/bash
# renew.sh
/srv/certbot-auto renew
cp /etc/letsencrypt/live/qieguo.me/* /alidata/server/nginx/conf/ssl/
/alidata/server/nginx/sbin/nginx -s reload
定时任务:
crontab -e
0 0 1 */3 * /alidata/renew-https-cert.sh
NOTE:写完定时任务记得启动sudo service cron restart
https应用中的一些注意点
http请求的重定向
用户直接在浏览器地址栏输入网址时,浏览器默认会使用http进行访问;另外你的链接被别人分享的时候,也很有可能被写成http网址,
所以很多服务器都在http页面上使用30x重定向跳转来使用https协议访问:
1 | server { |
这种模式不错,但是如果你的http页面被劫持了,那么用户根本到不了你的https页面,
也就意味着你精细准备的https根本派不上用场就被人截胡了。这时候你可以启动HSTS(HTTP Strict Transport Security)来让浏览器强制使用https访问。
HSTS可以让浏览器帮你做30x跳转,省一次HTTP请求。另外,浏览器本地替换可以保证只会发送HTTPS请求,避免被劫持。
要使用HSTS,只需要在你的HTTPS网站响应头中,加入下面这行:
strict-transport-security: max-age=16070400; includeSubDomains
includeSubDomains是可选的,用来指定是否作用于子域名。支持HSTS的浏览器遇到这个响应头,会把当前网站加入HSTS列表,
然后在max-age指定的秒数内,当前网站所有请求都会被重定向为https。即使用户主动输入http://或者不输入协议部分,都将重定向到https://地址。
但是HSTS需要浏览器先登录一次https页面之后才能生效,也就是说用户的首次登录仍然需要上述手动配置的rewrite跳转,这个环节的http访问依然有可能被劫持。如果你需要浏览器首次访问就直接强制使用https请求,那么你就需要在https://hstspreload.appspot.com登记你的域名,然后HSTS配置增加一个preload字段。如果你的网站通过审核,那么浏览器就会帮你做首次跳转了。
全站资源https化
决定要使用https之时,往往需要全站升级到https,避免出现Mixed Content的情况(在https站点中加载http资源)。因为加载的http资源如果是不安全的,那么启用https也没意义了。
另一方面,浏览器也越来越严格,Mixed Content资源在现代浏览器中可能已经加载不了了(尤其是js这种危险系数极高的资源)。
如果站点比较大,在全站往HTTPS迁移的过程中,工作量往往非常巨大,尤其是将所有资源都替换为 HTTPS 这一步,很容易产生疏漏。
这时候可以通过 upgrade-insecure-requests 这个 CSP 指令,可以让浏览器帮忙做这个转换。启用这个策略后,有两个变化:
- 页面所有 HTTP 资源,会被替换为 HTTPS 地址再发起请求;
- 页面所有站内链接,点击后会被替换为 HTTPS 地址再跳转;
其他一些配置
- 旧版本的SSL并不安全,所以我们应该启用新的TLS并选择安全的加密套件(算法)
1 | # 配置只支持tls协议 |
- 向前保密的概念很简单:客户端和服务器协商一个可靠的密钥,并在会话结束后销毁。服务器中的RSA私钥用来签名客户端和服务器之间交换的Diffie-Hellman密钥。副主密钥从Diffie-Hellman握手中得到,并用于加密。由于副主密钥在客户端和服务器之间的连接中是明确具体的,并用于有限的时间,因此被叫作Ephemeral(短暂的)。由于有Forward Secrecy,即使攻击者持有服务器的私钥,也不能够解密过去的会话。私钥仅仅用来签名DH(Diffie-Hellman)的握手,它并没有泄漏副主密钥。Diffie-Hellman确保了副主密钥不会离开客户端和服务器,也不会被中间人截获。
但由于我们正在使用一个2048位的证书,DHE客户端比非ephemeral客户端将使用一个更弱的密钥(1024位)交换。所以我们要单独生成一个2048位的DHE参数:
1 | #配置支持 Perfect Forward Secrecy |
- OCSP一次只获取一条记录。但是副作用是,当连接到服务器的时候,OCSP请求必须发送到第三方响应者,这增加了延迟,以及失败的可能。实际上,OCSP响应者由CA操控,由于它常常不可靠,导致浏览器由于收不到适时的响应而失败。这减少了安全性,因为它允许攻击者对OCSP响应者进行DoS攻击来取消验证。解决方案是在TLS握手期间,允许服务器发送缓存的OCSP记录,这样来绕过OCSP响应者。这个技术节省了在客户端和OCSP响应者之间的一个来回,称为OCSP闭合(OCSP Stapling)。服务器只在客户端请求的时候,发送一个缓存的OCSP响应,通过对CLIENT HELLO的status_request TLS拓展来声明支持。大多数服务器都会缓存OCSP响应到48小时。在常规间隔,服务器会连接到CA的OCSP响应者来获取最新的OCSP记录。OCSP响应者的位置是从签名证书的Authority Information Access 字段来获取。
OCSP(Online Certificate Status Protocol,在线证书状态协议)是维护服务器和其它网络资源安全性的两种普遍模式之一。OCSP克服了证书注销列表(CRL)的主要缺陷:必须经常在客户端下载以确保列表的更新。当用户试图访问一个服务器时,在线证书状态协议发送一个对于证书状态信息的请求。服务器回复一个“有效”、“过期”或“未知”的响应。协议规定了服务器和客户端应用程序的通讯语法。在线证书状态协议给了用户的到期的证书一个宽限期,这样他们就可以在更新以前的一段时间内继续访问服务器。
1 | # 配置支持 ocsp stapling |